package com.atom.module.coroutine.core

sealed class CoroutineState {
    class InComplete : CoroutineState() // 未完成的
    class Cancelling : CoroutineState() // 正在取消
    class Complete<T>(val value: T? = null, val exception: Throwable? = null) : CoroutineState()
    class CompleteWaitForChildren<T>(
        val value: T? = null,
        val exception: Throwable? = null,
        val isCancelling: Boolean = false
    ) : CoroutineState() {
        // 复制一份 子类的状态
        fun copy(value: T? = this.value, exception: Throwable? = this.exception, isCancelling: Boolean = this.isCancelling): CompleteWaitForChildren<T>{
            return CompleteWaitForChildren(value, exception, isCancelling).from(this) as CompleteWaitForChildren<T>
        }

        fun tryWaitForChildren(onChildComplete: (Job) -> Unit){
            //尾递归进行 遍历
            children.forEach { child ->
                // 递归判断 完成
                child.invokeOnCompletion {
                    // 完成后回调
                    onChildComplete(child)
                }
            }
        }
        // 拿到任意一个子类 进行 遍历 Job是否存在, 如果存在 且 为最后一个就直接完成 反之创建一个新的状态 并将Job 移除
        fun onChildCompleted(job: Job): CoroutineState {
            when(val currentChildren = children){
                is RecursiveList.Cons -> {
                    if(currentChildren.tail == RecursiveList.Nil
                        && currentChildren.head == job){
                            // 完成
                        return Complete(value, exception).from(this)
                    }
                }
            }
            return CompleteWaitForChildren(value, exception, isCancelling).from(this).without(job)
        }
    }

    protected var disposableList: RecursiveList<Disposable> = RecursiveList.Nil
        private set
    protected var children: RecursiveList<Job> = RecursiveList.Nil
        private set

    // 进行赋值
    fun from(state: CoroutineState): CoroutineState {
        this.disposableList = state.disposableList
        this.children = state.children
        return this
    }

    fun with(element: Any): CoroutineState {
        when (element) {
            is Disposable -> this.disposableList = RecursiveList.Cons(element, this.disposableList)
            is Job -> this.children = RecursiveList.Cons(element, this.children)
        }
        return this
    }

    fun without(element: Any): CoroutineState {
        when (element) {
            is Disposable -> this.disposableList = this.disposableList.remove(element)
            is Job -> this.children = this.children.remove(element)
        }
        return this
    }

    fun <T> notifyCompletion(result: Result<T>) {
        // 通知并检出 完成处理器 回调其完成监听 输入result
        this.disposableList.loopOn<CompletionHandlerDisposable<T>> {
            it.onComplete(result)
        }
    }

    fun notifyCancellation() {
        // 检出取消处理 , 并并执行其对应的取消操作
        this.disposableList.loopOn<CancellationHandlerDisposable> {
            it.onCancel()
        }
    }

    fun clear() {
        this.disposableList = RecursiveList.Nil
        this.children = RecursiveList.Nil
    }

    fun <T> tryComplete(result: Result<T>): CoroutineState {
        // 完成 后 创建并复制父类的
        return if (children == RecursiveList.Nil) // 子类未null 直接创建完成类对象 返回
            Complete(result.getOrNull(), result.exceptionOrNull()).from(this)
        else
            // 子类还有未完成的 返回一个子类等待完成的密封类对象 , 并复制一份数据
            // InComplete Complete Cancelling CompleteWaitForChildren
            CompleteWaitForChildren(
                result.getOrNull(),
                result.exceptionOrNull(),
                this is Cancelling
            ).from(this)
    }


    override fun toString(): String {
        return "CoroutineState.${this.javaClass.simpleName}"
    }
}